package com.xdf.whiteaccount.aop;

import com.xdf.whiteaccount.dao.ProductOutwardOrderMapper;
import com.xdf.whiteaccount.entity.Plan;
import com.xdf.whiteaccount.entity.ProductOutwardOrder;
import com.xdf.whiteaccount.enums.ResponseEnum;
import com.xdf.whiteaccount.service.CallService;
import com.xdf.whiteaccount.service.PlanService;
import com.xdf.whiteaccount.utils.CalculateUtil;
import com.xdf.whiteaccount.utils.Example;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.Optional;

/**
 * @program: white-account
 * @description:
 * @author: 张柯
 * @create: 2021-07-03 12:41
 **/
@Aspect
@Component
@Slf4j
public class ProductOutwardOrderServiceAspect extends AbstractAop {
    @Autowired
    private CallService callService;
    @Autowired
    private ProductOutwardOrderMapper dao;
    @Autowired
    private PlanService planService;

    @Pointcut("execution(* com.xdf.whiteaccount.service.ProductOutwardOrderService.insert*(..))")
    private void insertCut() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.service.ProductOutwardOrderService.update*(..))")
    private void updateCut() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.service.ProductOutwardOrderService.cancelByPk(..))")
    private void deleteCut() {
    }

    /**
     * 新增前
     *
     * @param joinPoint
     */
    @Before("insertCut()")
    @Transactional(rollbackFor = Exception.class)
    public void beforeInsert(JoinPoint joinPoint) throws Exception {
        Object param = getParam1(joinPoint);
        if (param instanceof ProductOutwardOrder) {
            ProductOutwardOrder record = (ProductOutwardOrder) param;
            Assert.notNull(record, ResponseEnum.NOT_ALLOW_EMPTY_DATA.getName());
            Assert.state(CollectionUtils.isNotEmpty(planService.listQuery(Plan.builder().planCode(record.getPlanCode()).build())), record.getPlanCode() + "不存在！");
            if (Optional.ofNullable(record).map(ProductOutwardOrder::getIsFinishedProduct).orElse(false)) {
                record.setIsFinishedProduct(true);
                if (record.getIsSendDirectly() == null) {
                    record.setIsSendDirectly(false);
                    record.setConsignee("");
                }
            } else {
                record.setIsFinishedProduct(false);
            }
            if (Optional.ofNullable(record).map(ProductOutwardOrder::getStorageId).orElse(0) > 0) {
                record.setOrderCode(callService.productOutwardOrderCodeGen(false));
            } else {
                record.setOrderCode(callService.productOutwardOrderCodeGen(record.getIsFinishedProduct()));
            }
            //  计算金额
            record.setMoney(CalculateUtil.mul(record.getProcessingCost(),record.getInputKilo()));
            record.setId(null);
            record.setCreateUserId(getLoginUserId());
            record.setCreateTime(new Date());
            record.setState(1);
        }
    }

    /**
     * 返回
     *
     * @param arg
     */
    @AfterReturning(value = "updateCut()", returning = "arg")
    @Transactional(rollbackFor = Exception.class)
    public void afterUpdate(JoinPoint joinPoint, int arg) throws Exception {
        if (arg > 0) {
            Object param = getParam1(joinPoint);
            if (param instanceof ProductOutwardOrder) {
                ProductOutwardOrder record = (ProductOutwardOrder) param;
                ProductOutwardOrder source = dao.selectByPrimaryKey(record.getId());
                Assert.state(!Optional.ofNullable(source).map(ProductOutwardOrder::getIsAudit).orElse(false), ResponseEnum.IS_AUDIT.getName());
                Assert.notNull(source, ResponseEnum.NOT_ALLOW_EMPTY_DATA.getName());
                if (source.getIsSendDirectly() != null && source.getIsSendDirectly()) {
                    ProductOutwardOrder modify = (ProductOutwardOrder) record.clone();
                    modify.setId(null);
                    modify.setState(null);
                    modify.setOrderCode(null);
                    modify.setLinkedOrderCode(null);
                    if (StringUtils.isNotEmpty(source.getLinkedOrderCode()))
                        dao.updateByExampleSelective(modify, new Example().andEq("order_code", source.getLinkedOrderCode()).andIsNull("storage_id"));
                    else
                        dao.updateByExampleSelective(modify, new Example().andEq("linked_order_code", source.getOrderCode()).andIsNull("storage_id"));
                }
                //  计算金额
                record.setMoney(CalculateUtil.mul(record.getProcessingCost(),record.getInputKilo()));
            }
        }
    }

    /**
     * @param joinPoint
     */
    @Before("deleteCut()")
    @Transactional(rollbackFor = Exception.class)
    public void beforeCancelById(JoinPoint joinPoint) {
        Object param = getParam1(joinPoint);
        if (param instanceof Long) {
            ProductOutwardOrder record = dao.selectByPrimaryKey((Long) param);
            Assert.state(!Optional.ofNullable(record).map(ProductOutwardOrder::getIsAudit).orElse(false), ResponseEnum.IS_AUDIT.getName());
        }
    }

    /**
     * 删除后事件
     *
     * @param joinPoint 参数
     * @param arg       返回值
     */
    @AfterReturning(value = "deleteCut()", returning = "arg")
    @Transactional(rollbackFor = Exception.class)
    public void afterCancelById(JoinPoint joinPoint, int arg) {
        if (arg > 0) {
            Object param = getParam1(joinPoint);
            if (param instanceof Long) {
                Long id = (Long) param;
                ProductOutwardOrder record = dao.selectByPrimaryKey(id);
                if (record != null) {
                    Example example;
                    if (StringUtils.isNotEmpty(record.getLinkedOrderCode())) {
                        example = new Example().andEq("order_code", record.getLinkedOrderCode()).andIsNull("storage_id");
                    } else {
                        example = new Example().andEq("linked_order_code", record.getOrderCode()).andIsNull("storage_id");
                    }
                    dao.updateByExampleSelective(ProductOutwardOrder.builder().state(0).build(), example);
                }
            }
        }
    }
}